use encoding_rs::GB18030;
use std::{error::Error, fs, path::PathBuf};

const ANSI_ENCODING: &encoding_rs::Encoding = GB18030;
fn read_file(path: &str) -> Result<String, Box<dyn Error>> {
    let bytes = fs::read(path)?;
    let (cow, _, _) = ANSI_ENCODING.decode(&bytes);
    Ok(cow.into_owned())
}
fn write_file(path: &str, content: &str) -> Result<(), Box<dyn Error>> {
    let (bytes, _uncoding_used_actually, _unmappable_exists) = ANSI_ENCODING.encode(content);
    fs::write(path, bytes)?;
    Ok(())
}
const ENHANCE: &str = r#"
const
  LicenseName = '{name}';
  LicenseKey = '{key}';

{$IFDEF VER150}
{$DEFINE XL_ANSI}
{$ENDIF}

const
  dllLibXL = 'libxl'{$IFDEF CPUX64} + '64'{$ENDIF};
  dllFunSuffix = {$IFDEF XL_ANSI} 'A'{$ELSE} 'W'{$ENDIF};

type
  PXLChar = {$IFDEF XL_ANSI}PAnsiChar{$ELSE}PWideChar{$ENDIF};
  XLString = {$IFDEF XL_ANSI}AnsiString{$ELSE}WideString{$ENDIF};
"#;

const LICENSE_NAME: &str = "admin";
const LICENSE_KEY: &str = "windows-2e2e21000cc3e1056ebb6a62acy7o5sb39c5c350";

fn main() -> Result<(), Box<dyn Error>> {
    let set_key = "  SetKey(LicenseName, LicenseKey);\r\n";
    let enhance = ENHANCE
        .replace("{name}", LICENSE_NAME)
        .replace("{key}", LICENSE_KEY);
    let bin = "constructor TBinBook.Create();\r\nbegin\r\n  inherited Create;\r\n  handle := xlCreateBookC;\r\n";
    let bin_to = bin.to_owned() + set_key;
    let xml = "constructor TXmlBook.Create();\r\nbegin\r\n  inherited Create;\r\n  handle := xlCreateXMLBookC;\r\n";
    let xml_to = xml.to_owned() + set_key;
    let util = "uses SysUtils;\r\n";
    let util_to = util.to_owned() + &enhance;
    let replaces = vec![
        ("'libxl'", "dllLibXL"),
        ("W';\r\n", "' + dllFunSuffix;\r\n"),
        ("PWideChar", "PXLChar"),
        ("WideString", "XLString"),
        (util, &util_to),
        (bin, &bin_to),
        (xml, &xml_to),
    ];

    let in_file = "d:/projects/components/LibXL4600/Delphi/LibXL.pas";
    let saved_file = in_file.replace("LibXL.pas", "LibXL.pas.saved");
    let content = if !PathBuf::from(&saved_file).exists() {
        let content = read_file(in_file)?;
        write_file(&saved_file, &content)?;
        content
    } else {
        read_file(&saved_file)?
    };
    let result = replaces
        .iter()
        .fold(content, |source, (find, replace_with)| {
            source.replace(find, replace_with)
        });
    let out_file = in_file;
    write_file(out_file, &result)?;
    println!("File saved to :{}\n", out_file);
    Ok(())
}
